import { ProColumns, ProTable } from '@/components/Pro';
import {
  batteryControllerGetBmsDatas,
  batteryControllerGetBmuDatas,
  batteryControllerGetClusterDatas,
  batteryControllerGetDeviceTreeDatas,
} from '@/services/ess/deviceBattery';
import { DATABASE_TYPE_ENUM, fetchDictInfo } from '@/utils';
import { formatterTree } from '@/utils/formatterTree';
import { useModel } from '@@/exports';
import { SearchOutlined } from '@ant-design/icons';
import { Flex, Input, Spin, Tree, TreeDataNode } from 'antd';
import cls from 'classnames';
import dayjs from 'dayjs';
import React, { useEffect, useRef, useState } from 'react';
import { getHiddenColumnKeysFromRecords, hideEmptyDataColumns } from '../helper';
import './HIstoryData.less';
import Styles from './HIstoryData.less';

const RUN_STATE: Record<string | number, { label: string; value: string }> = {
  0: {
    label: '静置',
    value: 'stop',
  },
  1: {
    label: '充电',
    value: 'charge',
  },
  2: {
    label: '放电',
    value: 'discharge',
  },
};

const ONLINE_STATE: Record<string | number, { label: string; value: string }> = {
  0: {
    label: '离线',
    value: 'offline',
  },
  1: {
    label: '在线',
    value: 'online',
  },
};

const HistoryData: React.FC = () => {
  const treeRef = useRef(null);
  const actionRef = useRef(null);
  const { initialState } = useModel('@@initialState');
  const [spinning, setSpining] = useState(false);
  const [dataList, setDataList] = useState();
  const [treeData, setTreeData] = useState<TreeDataNode[]>([]);
  const [selectedNode, setSelectedNode] = useState();
  const [expandedKeys, setExpandedKeys] = useState([]);
  // const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
  const [autoExpandParent, setAutoExpandParent] = useState(true);

  const timeRangeColumn: ProColumns = {
    title: '时间范围',
    dataIndex: 'timeRange',
    valueType: 'dateTimeRange',
    hideInTable: true,
    initialValue: [dayjs().subtract(1, 'hour'), dayjs()],
  };
  const correctColumn: ProColumns = {
    title: '是否有效',
    dataIndex: 'correct',
    valueType: 'select',
    valueEnum: {
      1: {
        text: '有效',
      },
      0: {
        text: '无效',
      },
    },
    render: (_, record) => {
      console.log('record', record);

      const value = record.correct;
      return value === 0 ? '无效' : value === 1 ? '有效' : '-';
    },
  };
  // const { Search } = Input;
  // 堆信息列表
  const stackColumns: ProColumns[] = [
    {
      title: '序号',
      dataIndex: 'pageIndex',
      hideInSearch: true,
      width: 60,
    },
    timeRangeColumn,
    {
      title: '采集时间',
      dataIndex: 'collectTime',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '上报时间',
      dataIndex: 'reportTime',
      hideInSearch: true,
      width: 100,
    },
    correctColumn,
    {
      title: '功率(kW)',
      dataIndex: 'power',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '电压(V)',
      dataIndex: 'voltage',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '电流(A)',
      dataIndex: 'current',
      hideInSearch: true,
      width: 100,
    },
    {
      title: 'SOC(%)',
      dataIndex: 'soc',
      hideInSearch: true,
      width: 90,
    },
    {
      title: '可放电量(kWh)',
      dataIndex: 'leftEnergy',
      hideInSearch: true,
      width: 120,
    },
    {
      title: '可充电量(kWh)',
      dataIndex: 'usedEnergy',
      hideInSearch: true,
      width: 120,
    },
    {
      title: '累计充电量(kWh)',
      dataIndex: 'inputEnergy',
      hideInSearch: true,
      width: 140,
    },
    {
      title: '累计放电量(kWh)',
      dataIndex: 'outputEnergy',
      hideInSearch: true,
      width: 140,
    },

    {
      title: '电池箱名称',
      dataIndex: 'boxName',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '电池堆名称',
      dataIndex: 'bmsName',
      hideInSearch: true,
      width: 100,
    },
  ];
  // 簇信息列表
  const clusterColumns: ProColumns[] = [
    {
      title: '序号',
      dataIndex: 'pageIndex',
      hideInSearch: true,
      fixed: 'left',
      width: 60,
    },
    timeRangeColumn,
    {
      title: '采集时间',
      dataIndex: 'collectTime',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '上报时间',
      dataIndex: 'reportTime',
      hideInSearch: true,
      width: 100,
    },
    correctColumn,
    {
      title: '电压(V)',
      dataIndex: 'voltage',
      hideInSearch: true,
    },
    {
      title: '电流(A)',
      dataIndex: 'current',
      hideInSearch: true,
    },
    {
      title: '功率(kW)',
      dataIndex: 'power',
      hideInSearch: true,
    },
    {
      title: 'SOC(%)',
      dataIndex: 'soc',
      hideInSearch: true,
    },
    {
      title: 'SOH(%)',
      dataIndex: 'soh',
      hideInSearch: true,
    },
    {
      title: 'SOE(%)',
      dataIndex: 'soe',
      hideInSearch: true,
    },
    {
      title: 'SOP(%)',
      dataIndex: 'sop',
      hideInSearch: true,
    },
    {
      title: 'SOF(%)',
      dataIndex: 'sof',
      hideInSearch: true,
    },
    {
      title: '正对地电阻(Ω)',
      dataIndex: 'pbusResistor',
      hideInSearch: true,
    },
    {
      title: '负对地电阻(Ω)',
      dataIndex: 'nbusResistor',
      hideInSearch: true,
    },
    {
      title: '可放电量(kWh)',
      dataIndex: 'leftEnergy',
      hideInSearch: true,
    },
    {
      title: '可充电量(kWh)',
      dataIndex: 'usedEnergy',
      hideInSearch: true,
    },
    {
      title: '日累计充电电量(kWh)',
      dataIndex: 'dayInputWatt',
      width: 120,
      hideInSearch: true,
    },
    {
      title: '日累计放电电量(kWh)',
      dataIndex: 'dayOutputWatt',
      width: 120,
      hideInSearch: true,
    },
    {
      title: '累计充电(AH)',
      dataIndex: 'inputAH',
      hideInSearch: true,
    },
    {
      title: '累计放电(AH)',
      dataIndex: 'outputAH',
      hideInSearch: true,
    },
    {
      title: '累计充电电量(kWh)',
      dataIndex: 'inputWatt',
      hideInSearch: true,
    },
    {
      title: '累计放电电量(kWh)',
      dataIndex: 'outputWatt',
      hideInSearch: true,
    },

    {
      title: 'BCMS在线状态',
      dataIndex: 'bcmsOnlineState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: 'BCU在线状态',
      dataIndex: 'bcuOnlineState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '充放电状态',
      dataIndex: 'bcSysState',
      hideInSearch: true,
      width: 150,
      valueType: 'select',
      request: () => fetchDictInfo(DATABASE_TYPE_ENUM.CHARGE_STATUS),
    },
    {
      title: '接触器状态',
      dataIndex: 'brkState',
      hideInSearch: true,
      width: 150,
      valueType: 'select',
      request: async () => [
        { label: '断开', value: '1' },
        { label: '闭合', value: '0' },
      ],
    },
    {
      title: '总断路器故障',
      dataIndex: 'mainBreakerState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '均衡模式',
      dataIndex: 'balanceMode',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '均衡手动模式使能',
      dataIndex: 'balanceManualModeEn',
      hideInSearch: true,
      width: 130,
      render: (_, record) => {
        return <span>{Number(record.balanceManualModeEn) === 1 ? '使能' : '失能'}</span>;
      },
    },
    {
      title: '均衡状态',
      dataIndex: 'balanceState',
      hideInSearch: true,
      width: 100,
      render: (_, record) => {
        return <span>{Number(record.balanceState) === 1 ? '正在均衡' : '不均衡'}</span>;
      },
    },
    {
      title: '风扇状态',
      dataIndex: 'fanState',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '风扇故障',
      dataIndex: 'fanFault',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '限功率状态字',
      dataIndex: 'limitPowerState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '告警状态字',
      dataIndex: 'warnState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '保护状态字',
      dataIndex: 'prtState',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '充电功率限值',
      dataIndex: 'limitChgPower',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '放电功率限值',
      dataIndex: 'limitDchgPower',
      hideInSearch: true,
      width: 150,
    },

    {
      title: '电池箱名称',
      dataIndex: 'boxName',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '电池堆名称',
      dataIndex: 'bmsName',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '电池簇名称',
      dataIndex: 'clusterName',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '簇BMU平均电压(V)',
      dataIndex: 'bmuAvgVol',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体平均电压(V)',
      dataIndex: 'cellAvgVol',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体平均温度(℃)',
      dataIndex: 'cellAvgTemp',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体最大压差(V)',
      dataIndex: 'volDifMax',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体最大温差(℃)',
      dataIndex: 'tempDifMax',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体最大电压(V)',
      dataIndex: 'vmax',
      hideInSearch: true,
      width: 150,
    },
    {
      title: '簇单体最大电压包索引',
      dataIndex: 'vmaxBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最大电压包内索引',
      dataIndex: 'vmaxCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二大电压(V)',
      dataIndex: 'vmaxSec',
      hideInSearch: true,
    },
    {
      title: '簇单体第二电压包索引',
      dataIndex: 'vmaxSecBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二电压包内索引',
      dataIndex: 'vmaxSecCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最小电压(V)',
      dataIndex: 'vmin',
      hideInSearch: true,
    },
    {
      title: '簇单体最小电压包索引',
      dataIndex: 'vminBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最小电压包内索引',
      dataIndex: 'vminCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小电压(V)',
      dataIndex: 'vminSec',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小电压包索引',
      dataIndex: 'vminSecBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小电压包内索引',
      dataIndex: 'vminSecCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最大温度(℃)',
      dataIndex: 'tmax',
      hideInSearch: true,
    },
    {
      title: '簇单体最大温度包索引',
      dataIndex: 'tmaxBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最大温度包内索引',
      dataIndex: 'tmaxCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二大温度(℃)',
      dataIndex: 'tmaxSec',
      hideInSearch: true,
    },
    {
      title: '簇单体第二大温度包索引',
      dataIndex: 'tmaxSecBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二大温度包内索引',
      dataIndex: 'tmaxSecCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最小温度(℃)',
      dataIndex: 'tmin',
      hideInSearch: true,
    },
    {
      title: '簇单体最小温度包索引',
      dataIndex: 'tminBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体最小温度包内索引',
      dataIndex: 'tminCellIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小温度(℃)',
      dataIndex: 'tminSec',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小温度包索引',
      dataIndex: 'tminSecBmuIdx',
      hideInSearch: true,
    },
    {
      title: '簇单体第二小温度包内索引',
      dataIndex: 'tminSecCellIdx',
      hideInSearch: true,
    },
  ];
  // 模组信息列表
  const moduleColumns: ProColumns[] = [
    {
      title: '序号',
      valueType: 'index',
      dataIndex: 'pageIndex',
      hideInSearch: true,
      fixed: 'left',
      width: 60,
    },
    timeRangeColumn,
    {
      title: '采集时间',
      dataIndex: 'collectTime',
      hideInSearch: true,
      width: 100,
    },
    {
      title: '上报时间',
      dataIndex: 'reportTime',
      hideInSearch: true,
      width: 100,
    },

    {
      title: '电流(A)',
      dataIndex: 'current',
      hideInSearch: true,
    },
    {
      title: '均衡电流(A)',
      dataIndex: 'bcurrent',
      hideInSearch: true,
      width: 130,
    },
    {
      title: '可充电量(kWh)',
      dataIndex: 'soh',
      width: 120,
      hideInSearch: true,
    },
    {
      title: '最大电压(V)',
      dataIndex: 'vmax',
      hideInSearch: true,
    },
    {
      title: '最大电压位置',
      dataIndex: 'vmaxIdx',
      hideInSearch: true,
      width: 120,
    },
    {
      title: '最小电压(V)',
      dataIndex: 'vmin',
      hideInSearch: true,
    },
    {
      title: '最小电压位置',
      dataIndex: 'vminIdx',
      hideInSearch: true,
      width: 120,
    },
    {
      title: '最大温度(℃)',
      dataIndex: 'tmax',
      hideInSearch: true,
    },
    {
      title: '最大温度位置',
      dataIndex: 'tmaxIdx',
      hideInSearch: true,
      width: 120,
    },
    {
      title: '最小温度(℃)',
      dataIndex: 'tmin',
      hideInSearch: true,
    },
    {
      title: '最小温度位置',
      dataIndex: 'tminIdx',
      hideInSearch: true,
      width: 120,
    },

    {
      title: '模组名称',
      dataIndex: 'bmuName',
      hideInSearch: true,
    },
    {
      title: '模组总压(V)',
      dataIndex: 'voltage',
      hideInSearch: true,
      width: 130,
    },
    {
      title: '单体平均电压(V)',
      dataIndex: 'cellAvgVol',
      width: 140,
      hideInSearch: true,
    },

    {
      title: '单体平均温度(℃)',
      dataIndex: 'cellAvgTemp',
      width: 150,
      hideInSearch: true,
    },
  ];
  const [tableColumns, setTableColumns] = useState<ProColumns[]>(stackColumns);

  const scroll = {
    x: 'max-content',
  };
  const handleSelectTreeNode = (selectedKeys: number, e) => {
    setSelectedNode(e.node);
    // setAutoExpandParent(false);
  };
  const getModuleTable = (options: API.Pagination) => {
    if (options.records && options.records.length > 0) {
      const tempDataArray = options?.records[0].tempData.split(';');
      const volDataArray = options?.records[0].voltData.split(';');
      const volColumnsArray = volDataArray.map((item, index) => {
        return {
          title: `单元${index + 1}电压(V)`,
          dataIndex: `UnitVol${index + 1}`,
          hideInSearch: true,
          width: 120,
        };
      });
      const tempColumnsArray = tempDataArray.map((item, index) => {
        return {
          title: `单元${index + 1}温度(℃)`,
          dataIndex: `UnitTemp${index + 1}`,
          hideInSearch: true,
          width: 120,
        };
      });
      const getRecords = options?.records.map((item) => {
        const tempArray = item.tempData ? item.tempData.split(';') : [];
        const volArray = item.voltData ? item.voltData.split(';') : [];
        const getTempArray: any = {};
        tempArray.forEach((tItem, index) => {
          getTempArray[`UnitTemp${index + 1}`] = tItem;
        });
        const getVolArray: any = {};
        volArray.forEach((vItem, index) => {
          getVolArray[`UnitVol${index + 1}`] = vItem;
        });
        return {
          ...item,
          ...getTempArray,
          ...getVolArray,
        };
      });

      const hiddenColumnKeys = getHiddenColumnKeysFromRecords(getRecords);
      const columns = hideEmptyDataColumns(
        [...moduleColumns, ...volColumnsArray, ...tempColumnsArray],
        hiddenColumnKeys,
      );

      setTableColumns(columns);

      return {
        records: getRecords,
      };
    } else {
      return {
        records: [],
      };
    }
  };
  const onExpand = (expandedKeys: React.Key[]) => {
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(false);
  };
  /**
   * 获得第一组展开树的ID
   * @param tree
   */
  const getFirstExpandId = (tree: any) => {
    const idArray: string[] | number[] = [];

    function getId(arr: any) {
      idArray.push(arr[0]?.id);
      if (arr[0].children.length > 0) {
        getId(arr[0].children);
      }
    }

    getId(tree);
    return idArray;
  };
  const getParentKey = (key: React.Key, tree: TreeDataNode[]): React.Key => {
    let parentKey: React.Key;
    for (let i = 0; i < tree.length; i++) {
      const node = tree[i];
      if (node.children) {
        if (node.children.some((item) => item.id === key)) {
          parentKey = node.id;
        } else if (getParentKey(key, node.children)) {
          parentKey = getParentKey(key, node.children);
        }
      }
    }
    return parentKey!;
  };
  useEffect(() => {
    setSpining(true);
    batteryControllerGetDeviceTreeDatas({ stationId: initialState?.stationId })
      .then((res) => {
        if (res.data) {
          const combined = [
            ...(res?.data?.deviceBmsInfos || []),
            ...(res?.data?.deviceBmuInfos || []),
            ...(res?.data?.deviceBoxInfos || []),
            ...(res?.data?.deviceClusterInfos || []),
            ...(res?.data?.deviceGlcInfos || []),
            ...(res.data?.deviceLcClusterInfos || []),
            ...(res?.data?.deviceLcInfos || []),
          ];
          setDataList(combined);
          setTreeData(formatterTree(combined));
          setExpandedKeys(getFirstExpandId(formatterTree(combined)));
          setSelectedNode(res?.data?.deviceBmuInfos[0]);
          setSpining(false);
        } else {
          setSpining(false);
        }
      })
      .catch(() => {
        setSpining(false);
      });
  }, []);

  const filterTree = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    const newExpandedKeys = dataList
      .map((item) => {
        if (item.name.indexOf(value) > -1) {
          return getParentKey(item.id, treeData);
        }
        return null;
      })
      .filter((item, i, self): item is React.Key => item && self.indexOf(item) === i);
    setExpandedKeys(newExpandedKeys);
    setAutoExpandParent(true);
  };

  return (
    <div style={{ background: '#fff', padding: '0 24px 30px 24px' }}>
      <Flex className={Styles.HistoryData}>
        <Spin spinning={spinning} wrapperClassName="history-left-spin">
          <div
            style={{
              width: 300,
              minWidth: 300,
              paddingRight: 25,
              marginRight: 25,
              borderRight: '1px solid #e0e0e0',
              position: 'sticky',
              top: 68,
            }}
          >
            <Input
              style={{ marginBottom: 8 }}
              placeholder={'请输入'}
              addonAfter={<SearchOutlined />}
              onChange={(e) => {
                filterTree(e);
              }}
            ></Input>
            <Tree
              autoExpandParent={autoExpandParent}
              ref={treeRef}
              height={600}
              expandedKeys={expandedKeys}
              selectedKeys={[selectedNode?.id]}
              treeData={treeData}
              fieldNames={{
                title: 'name',
                key: 'id',
                children: 'children',
              }}
              titleRender={(treeDataNode) => {
                const node = treeDataNode as API.DeviceInfoDTO;
                const runState = RUN_STATE[node.runState as string];
                const onlineState = ONLINE_STATE[node.onlineState as number];
                return (
                  <div style={{ padding: '4px 0' }}>
                    <p style={{ margin: 0 }}>{node.name}</p>
                    <div
                      style={{
                        display: 'flex',
                        gap: 4,
                        alignItems: 'center',
                        flexWrap: 'wrap',
                      }}
                    >
                      {node.soc !== null && (
                        <p className="htn-badge htn-badge-soc">{`${node.soc}%`}</p>
                      )}
                      {node.runState !== null && runState && (
                        <p className={`htn-badge htn-badge-${runState.value}`}>{runState.label}</p>
                      )}
                      {node.onlineState !== null && onlineState && (
                        <p className={`htn-badge htn-badge-${onlineState.value}`}>
                          {onlineState.label}
                        </p>
                      )}
                      {/* {!!node.faultCount && (
                        <p className="htn-badge htn-badge-fault">{`故障 ${
                          node.faultCount > 99 ? '99+' : node.faultCount
                        }`}</p>
                      )} */}
                    </div>
                  </div>
                );
              }}
              onSelect={handleSelectTreeNode}
              onExpand={onExpand}
            ></Tree>
          </div>
        </Spin>

        <div style={{ width: 'calc(100% - 325px)' }}>
          <ProTable
            headerTitle=" "
            className={cls([Styles.hisTable, Styles.noTableTitle])}
            style={{
              position: 'relative',
              zIndex: '10',
              marginTop: '-45px',
            }}
            scroll={scroll}
            rowKey={'pageIndex'}
            columns={tableColumns}
            params={{
              code: selectedNode?.code,
            }}
            search={{
              // 每个字段占据列数
              span: { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 8 },
              defaultCollapsed: false,
              labelWidth: 80,
            }}
            actionRef={actionRef}
            request={async (values) => {
              if (!selectedNode) return false;
              const params = {
                current: values.current,
                pageSize: values.pageSize,
                stationId: initialState?.stationId,
                code: selectedNode.code,
                startTime: values.timeRange[0],
                endTime: values.timeRange[1],
                correct: values.correct,
              };
              switch (selectedNode.type) {
                case 'BMS': {
                  const res = await batteryControllerGetBmsDatas(params);
                  if (res.data?.records) {
                    const hiddenColumnKeys = getHiddenColumnKeysFromRecords(res.data.records);
                    const columns = hideEmptyDataColumns(stackColumns, hiddenColumnKeys);
                    setTableColumns(columns);
                  } else {
                    setTableColumns(stackColumns);
                  }
                  return res;
                }
                case 'CLUSTER': {
                  const res = await batteryControllerGetClusterDatas(params);
                  if (res.data?.records) {
                    const hiddenColumnKeys = getHiddenColumnKeysFromRecords(res.data.records);
                    const columns = hideEmptyDataColumns(clusterColumns, hiddenColumnKeys);
                    setTableColumns(columns);
                  } else {
                    setTableColumns(clusterColumns);
                  }
                  return res;
                }
                case 'BMU': {
                  setTableColumns(moduleColumns);
                  const res = await batteryControllerGetBmuDatas(params);
                  return {
                    data: getModuleTable(res.data).records,
                    success: true,
                    total: res.data.total,
                  };
                }
                default:
                  return false;
              }
            }}
          ></ProTable>
        </div>
      </Flex>
    </div>
  );
};

export default HistoryData;
